package com.bfly.mall.system.controller;

import com.alibaba.fastjson.JSONObject;
import com.bfly.common.ResponseUtil;
import com.bfly.common.util.StringUtil;
import com.bfly.core.base.controller.BaseController;
import com.bfly.core.base.entity.ResponseData;
import com.bfly.mall.system.dto.*;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.management.CacheStatistics;
import net.sf.ehcache.statistics.LiveCacheStatistics;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.VirtualMemory;

import javax.servlet.http.HttpServletResponse;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 操作系统参数信息Controller
 *
 * @author 长沙商脉科技有限公司
 * @date 2020/12/23 21:31
 */
@RestController
@RequestMapping(value = "/manage/system")
public class SystemInfoController extends BaseController {

    @Autowired
    private EhCacheCacheManager cacheManager;


    /**
     * 获得系统相关参数
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/12/23 21:32
     */
    @GetMapping(value = "/params")
    public void listSysParams(HttpServletResponse response) throws Exception {
        Map<String, String> map = System.getenv();
        InetAddress addr = InetAddress.getLocalHost();
        Properties props = System.getProperties();

        JSONObject json = new JSONObject();
        OSInfoDTO osInfoDTO = new OSInfoDTO();
        osInfoDTO.setComputerName(map.get("COMPUTERNAME"));
        osInfoDTO.setIp(addr.getHostAddress());
        osInfoDTO.setOsName(props.getProperty("os.name"));
        osInfoDTO.setOsArch(props.getProperty("os.arch"));
        osInfoDTO.setOsVersion(props.getProperty("os.version"));
        osInfoDTO.setTimeZone(props.getProperty("user.timezone"));
        json.put("os", osInfoDTO);

        Runtime r = Runtime.getRuntime();
        RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
        long minutes = bean.getUptime() / (1000 * 60);   //分钟

        JvmInfoDTO jvmInfoDTO = new JvmInfoDTO();
        jvmInfoDTO.setJavaHome(props.getProperty("java.home"));
        jvmInfoDTO.setJavaVendor(props.getProperty("java.vendor"));
        jvmInfoDTO.setJavaVersion(props.getProperty("java.version"));
        jvmInfoDTO.setTotalMemory(StringUtil.getHumanSize(r.totalMemory()));
        jvmInfoDTO.setFreeMemory(StringUtil.getHumanSize(r.freeMemory()));
        jvmInfoDTO.setRunTime(minutes);
        jvmInfoDTO.setStartTime(new Date(bean.getStartTime()));
        json.put("jvm", jvmInfoDTO);

        SystemInfo sysInfo = new SystemInfo();
        CentralProcessor cpu = sysInfo.getHardware().getProcessor();
        long[] prevTicks = cpu.getSystemCpuLoadTicks();
        TimeUnit.SECONDS.sleep(1);
        long[] ticks = cpu.getSystemCpuLoadTicks();

        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softIrq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long ioWait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long totalCpu = user + nice + cSys + idle + ioWait + irq + softIrq + steal;

        CpuInfoDTO cpuInfoDTO = new CpuInfoDTO();
        cpuInfoDTO.setTotal(cpu.getLogicalProcessorCount());
        cpuInfoDTO.setCombinedRate(new DecimalFormat("#.##%").format(1.0 - (idle * 1.0 / totalCpu)));
        cpuInfoDTO.setIdleRate(new DecimalFormat("#.##%").format(idle * 1.0 / totalCpu));
        cpuInfoDTO.setNiceRate(new DecimalFormat("#.##%").format(nice * 1.0 / totalCpu));
        cpuInfoDTO.setSysRate(new DecimalFormat("#.##%").format(cSys * 1.0 / totalCpu));
        cpuInfoDTO.setUserRate(new DecimalFormat("#.##%").format(user * 1.0 / totalCpu));
        cpuInfoDTO.setWaitRate(new DecimalFormat("#.##%").format(ioWait * 1.0 / totalCpu));
        json.put("cpu", cpuInfoDTO);

        GlobalMemory memory = sysInfo.getHardware().getMemory();
        VirtualMemory virtualMemory = memory.getVirtualMemory();
        long totalMemory = memory.getTotal();
        long availableMemory = memory.getAvailable();
        long swapTotal = virtualMemory.getSwapTotal();
        long availableSwap = virtualMemory.getSwapTotal() - virtualMemory.getSwapUsed();

        MemoryInfoDTO memoryInfoDTO = new MemoryInfoDTO();
        memoryInfoDTO.setTotal(totalMemory);
        memoryInfoDTO.setFree(availableMemory);
        memoryInfoDTO.setUsed(totalMemory - availableMemory);
        memoryInfoDTO.setSwapTotal(swapTotal);
        memoryInfoDTO.setSwapFree(availableSwap);
        memoryInfoDTO.setSwapUsed(virtualMemory.getSwapUsed());

        json.put("memory", memoryInfoDTO);

        ResponseUtil.writeJson(response, ResponseData.getSuccess(json));
    }

    /**
     * 获得缓存相关参数
     *
     * @author 长沙商脉科技有限公司
     * @date 2021/1/3 21:09
     */
    @GetMapping(value = "/cache")
    public void listCacheParams(HttpServletResponse response) {
        CacheManager ehcacheManager = this.cacheManager.getCacheManager();
        String[] names = ehcacheManager.getCacheNames();
        List<EhcacheInfoDTO> list = new ArrayList<>();
        for (String name : names) {
            Ehcache ehcache = ehcacheManager.getEhcache(name);

            EhcacheInfoDTO dto = new EhcacheInfoDTO();
            dto.setName(name);
            dto.setStatisticsEnabled(ehcache.isStatisticsEnabled());
            dto.setStatus(ehcache.getStatus().toString());
            dto.setSize(ehcache.getSize());
            dto.setAverageGetTime(ehcache.getAverageGetTime());

            LiveCacheStatistics liveCacheStatistics = ehcache.getLiveCacheStatistics();
            CacheStatistics cacheStatistics = new CacheStatistics(ehcache);

            long memory = liveCacheStatistics.getLocalHeapSizeInBytes() + liveCacheStatistics.getLocalOffHeapSizeInBytes();
            long disk = liveCacheStatistics.getLocalDiskSizeInBytes();

            dto.setMemorySize(memory);
            dto.setDiskSize(disk);
            dto.setHits(cacheStatistics.getCacheHitPercentage() * 100 + "%");
            dto.setMisses(cacheStatistics.getCacheMisses() * 100 + "%");

            list.add(dto);
        }
        ResponseUtil.writeJson(response, ResponseData.getSuccess(list));
    }
}
